<template>
  <div class="pagination">
    <button :disabled="myCurrentPage === 1" :class="{disable: myCurrentPage === 1}" @click="setCurrentPage(myCurrentPage - 1)">上一页</button>
    <button v-if="startEnd.start != 1" @click="setCurrentPage(1)">1</button>
    <button class="disable" v-if="startEnd.start > 2">...</button>
    <!-- 
      存在问题:
        多执行了从 1 到 start-1 的 v-for 和 v-if 的判断,不推荐使用
     -->
    <!-- <button v-for="item in startEnd.end" v-if="item >= startEnd.start" :class="{active: item === myCurrentPage }" @click="setCurrentPage(item)">{{item}}</button> -->
    <button v-for="item in startEndArr" :key="item" :class="{active: item === myCurrentPage }" @click="setCurrentPage(item)">{{item}}</button>
    <button class="disable" v-if="startEnd.end < totalPages - 1">...</button>
    <button v-if="startEnd.end < totalPages" @click="setCurrentPage(totalPages)">{{ totalPages }}</button>
    <button :disabled="myCurrentPage === totalPages" :class="{disable: myCurrentPage === totalPages}" @click="setCurrentPage(myCurrentPage + 1)">下一页</button>
    <button class="disable">共 {{ total }} 条</button>
  </div>
</template>

<script>
export default {
  name: 'MyPagination',
  props: {
    // 当前页码
    currentPage: {
      type: Number,
      default: 1
    },
    // 所有数据的总数量
    total: {
      type: Number,
      default: 0
    },
    // 每页的最大数量
    pageSize: {
      type: Number,
      default: 10
    },
    // 最大连续页码数
    showPageNo: {
      type: Number,
      default: 5,
      // 要求传的值是奇数,这样能保持当前页码在正中间,比较美观
      validator: function (value) {
        return value % 2 === 1
      }
    }
  },
  data () {
    return {
      // 初始值由父组件来指定
      myCurrentPage: this.currentPage
    }
  },
  computed: {
    // 总页数
    totalPages () {
      const { total, pageSize } = this
      return Math.ceil(total / pageSize)
    },
    /*
      连续页码数的开始页码与结束页码, start 和 end
      myCurrentPage     showPageNo      totalPages
        4               5              23[5]56
      
      start = (5 - 1) / 2 = 2
      end = 2 + 5 - 1
    */
    startEnd () {
      let start, end
      const { myCurrentPage, showPageNo, totalPages } = this

      // start = myCurrentPage - (showPageNo - 1) / 2
      start = myCurrentPage - Math.floor(showPageNo / 2)
      // 如果 myCurrentPage 比较小,则计算结果可能小于 1, start 要求 >= 1
      if (start < 1) {
        start = 1
      }
      end = start + showPageNo - 1
      // end 的最大值为 totalPages
      if (end > totalPages) {
        end = totalPages
        // 修正 start
        start = end - showPageNo + 1
        // 如果总页数小于最大连续页码数,则 start < 1
        if (start < 1) {
          start = 1
        }
      }
      return { start, end }
    },
    // 包含从 start 到 end 的数组
    startEndArr () {
      const arr = []
      const { start, end } = this.startEnd
      for (let page = start; page <= end; page++) {
        arr.push(page)
      }
      return arr
    }
  },
  methods: {
    // 设置新的当前页码
    setCurrentPage (page) {
      if (this.currentPage !== page) {
        this.myCurrentPage = page
        // 触发自定义事件通过父组件
        this.$emit('currentChange', page)
      }
    }
  },
  watch: {
    // 子组件监视父组件传入的数据变化
    currentPage (value) {
      this.myCurrentPage = value
    }
  }
}
</script>

<style lang="less" scoped>
.pagination {
  button {
    margin: 0 5px;
    background-color: #f4f4f5;
    color: #606266;
    outline: none;
    border-radius: 2px;
    padding: 0 4px;
    vertical-align: top;
    display: inline-block;
    font-size: 13px;
    min-width: 35.5px;
    height: 28px;
    line-height: 28px;
    cursor: pointer;
    box-sizing: border-box;
    text-align: center;
    border: 0;

    // 当前页按钮高亮
    &.active {
      background: blue;
      color: white;
      // 鼠标禁用效果
      cursor: not-allowed;
    }

    &.disable {
      // 鼠标禁用效果
      cursor: not-allowed;
      color: #ccc;
    }
  }
}
</style>